package search;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import models.OrderModel;
import com.google.appengine.api.search.Index;
import com.google.appengine.api.search.IndexSpec;
import com.google.appengine.api.search.Query;
import com.google.appengine.api.search.QueryOptions;
import com.google.appengine.api.search.Results;
import com.google.appengine.api.search.ScoredDocument;
import com.google.appengine.api.search.SearchServiceFactory;

public class OrderSearchData {

	private static Index INDEX = SearchServiceFactory.getSearchService()
			.getIndex(IndexSpec.newBuilder().setName("order"));
	private static final Logger log = Logger.getLogger(OrderSearchData.class
			.getName());

	private int limit = 10;

	private int page = 1;

	private int totalResult = 0;

	private int totalReturn = 0;

	private int totalMoney = 0;

	private int recentMoney = 0;

	private OrderModel currentItem = new OrderModel();

	private List<OrderModel> listResult = new ArrayList<OrderModel>();

	public int getLimit() {
		return limit;
	}

	public void setLimit(int limit) {
		this.limit = limit;
	}

	public OrderModel getCurrentItem() {
		return currentItem;
	}

	public void setCurrentItem(OrderModel currentItem) {
		this.currentItem = currentItem;
	}

	public boolean isHasNextPage() {
		if (totalResult != 0) {
			return totalResult > (page * limit);
		} else {
			return false;
		}
	}

	public boolean isHasPreviousPage() {
		return page > 1;
	}

	public int getRecentMoney() {
		return recentMoney;
	}

	public int getTotalMoney() {
		return totalMoney;
	}

	public void setTotalMoney(int totalMoney) {
		this.totalMoney = totalMoney;
	}

	public int getTotalResult() {
		return totalResult;
	}

	public int getTotalReturn() {
		return totalReturn;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public List<OrderModel> getListResult() {
		return listResult;
	}

	public void setListResult(List<OrderModel> listResult) {
		this.listResult = listResult;
	}

	public void prepareList() {
		try {
			listResult = new ArrayList<OrderModel>();
			Query query = Query
					.newBuilder()
					.setOptions(
							QueryOptions.newBuilder().setLimit(limit)
									.setOffset(limit * (page - 1)).build())
					.build("");

			Results<ScoredDocument> docResult = INDEX.search(query);
			totalResult = (int) docResult.getNumberFound();
			totalReturn = (int) docResult.getNumberReturned();
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					listResult.add(OrderSearchEngine
							.documentToObjectByReflection(scoredDocument));
				}
			}
		} catch (Exception e) {
			System.out.println("Error when try to prepare list order !");
			log.warning("Error when try to prepare list order !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void search(String username, Date fromDate, Date toDate,
			int fromPrice, int toPrice) {
		try {
			StringBuilder queryString = new StringBuilder();
			Calendar cal = Calendar.getInstance();
			if (username != null && !username.isEmpty()) {
				queryString.append("username:" + username);
			}
			if (fromDate != null) {
				String fromDateString;
				cal.setTime(fromDate);
				fromDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) - 1);
				queryString.append(" AND orderDate > " + fromDateString);
			}
			if (toDate != null) {
				String toDateString;
				cal.setTime(toDate);
				toDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) + 1);
				queryString.append(" AND orderDate < " + toDateString);
			}
			if (fromPrice > 0) {
				queryString.append(" AND totalPrice >=" + fromPrice);
			}
			if (toPrice > 0) {
				queryString.append(" AND totalPrice <=" + toPrice);
			}
			System.out.println(queryString.toString());
			listResult = new ArrayList<OrderModel>();
			Query query = Query.newBuilder()
					.setOptions(QueryOptions.newBuilder().build())
					.build(queryString.toString());

			Results<ScoredDocument> docResult = INDEX.search(query);
			totalResult = (int) docResult.getNumberFound();
			totalReturn = (int) docResult.getNumberReturned();
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					listResult.add(OrderSearchEngine
							.documentToObjectByReflection(scoredDocument));
				}
			}
		} catch (Exception e) {
			System.out.println("Error when try to search order !");
			log.warning("Error when try to search order !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void searchOrderByWard(String ward) {
		try {
			StringBuilder queryString = new StringBuilder();
			if (ward != null && !ward.isEmpty()) {
				queryString.append("shipWard:" + ward);
			}
			queryString.append(" AND status = 1");
			queryString.append(" AND shipType = 1");
			queryString
					.append(" AND ((paymentType = 1 AND checkOut = false) OR (paymentType = 2 AND checkOut = true))");
			listResult = new ArrayList<OrderModel>();
			Query query = Query.newBuilder()
					.setOptions(QueryOptions.newBuilder().build())
					.build(queryString.toString());

			Results<ScoredDocument> docResult = INDEX.search(query);
			totalResult = (int) docResult.getNumberFound();
			totalReturn = (int) docResult.getNumberReturned();
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					listResult.add(OrderSearchEngine
							.documentToObjectByReflection(scoredDocument));
				}
			}
		} catch (Exception e) {
			System.out.println("Error when try to search order !");
			log.warning("Error when try to search order !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void searchByEmailMarketing(Date fromDate, Date toDate) {
		try {
			StringBuilder queryString = new StringBuilder();
			Calendar cal = Calendar.getInstance();
			if (fromDate != null) {
				String fromDateString;
				cal.setTime(fromDate);
				fromDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) - 1);
				queryString.append("orderDate > " + fromDateString + " ");
			}
			if (toDate != null) {
				String toDateString;
				cal.setTime(toDate);
				toDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) + 1);
				if (fromDate != null) {
					queryString.append("AND orderDate < " + toDateString + " ");
				} else {
					queryString.append("orderDate < " + toDateString + " ");
				}
			}

			queryString.append("fromEmail:1");
			listResult = new ArrayList<OrderModel>();
			Query query = Query.newBuilder().build(queryString.toString());

			Results<ScoredDocument> docResult = INDEX.search(query);
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					listResult.add(OrderSearchEngine
							.documentToObjectByReflection(scoredDocument));
				}
			}
		} catch (Exception e) {
			System.out.println("Error when try to search order by date !");
			log.warning("Error when try to search order by date !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void searchByDate(Date fromDate, Date toDate) {
		try {
			StringBuilder queryString = new StringBuilder();
			Calendar cal = Calendar.getInstance();
			if (fromDate != null) {
				String fromDateString;
				cal.setTime(fromDate);
				fromDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) - 1);
				queryString.append("orderDate > " + fromDateString);
			}
			if (toDate != null) {
				String toDateString;
				cal.setTime(toDate);
				toDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) + 1);
				if (fromDate != null) {
					queryString.append(" AND orderDate < " + toDateString);
				} else {
					queryString.append("orderDate < " + toDateString);
				}
			}
			listResult = new ArrayList<OrderModel>();
			Query query = Query.newBuilder().build(queryString.toString());

			Results<ScoredDocument> docResult = INDEX.search(query);
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					listResult.add(OrderSearchEngine
							.documentToObjectByReflection(scoredDocument));
				}
			}
		} catch (Exception e) {
			System.out.println("Error when try to search order by date !");
			log.warning("Error when try to search order by date !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void searchByCheckOutDate(Date fromDate, Date toDate) {
		try {
			StringBuilder queryString = new StringBuilder();
			Calendar cal = Calendar.getInstance();
			if (fromDate != null) {
				String fromDateString;
				cal.setTime(fromDate);
				fromDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) - 1);
				queryString.append("checkOutTime > " + fromDateString);
			}
			if (toDate != null) {
				String toDateString;
				cal.setTime(toDate);
				toDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) + 1);
				if (fromDate != null) {
					queryString.append(" AND checkOutTime < " + toDateString);
				} else {
					queryString.append("checkOutTime < " + toDateString);
				}
			}
			listResult = new ArrayList<OrderModel>();			
			Query query = Query.newBuilder().build(queryString.toString());
			System.out.println(queryString.toString());
			Results<ScoredDocument> docResult = INDEX.search(query);
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					listResult.add(OrderSearchEngine
							.documentToObjectByReflection(scoredDocument));
				}
			}	
			for (OrderModel ord : listResult) {
				System.out.println(ord.getDealName());
				System.out.println(ord.getTotalPrice());				
			}
		} catch (Exception e) {
			System.out.println("Error when try to search order by date !");
			log.warning("Error when try to search order by date !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void searchByUser(String username) {
		try {
			listResult = new ArrayList<OrderModel>();
			String queryString = "username:" + username;
			Query query = Query.newBuilder()
					.setOptions(QueryOptions.newBuilder().build())
					.build(queryString);
			// Query query = Query
			// .newBuilder()
			// .setOptions(
			// QueryOptions.newBuilder().setLimit(limit)
			// .setOffset(limit * (page - 1)).build())
			// .build(queryString.toString());

			Results<ScoredDocument> docResult = INDEX.search(query);
			totalResult = (int) docResult.getNumberFound();
			totalReturn = (int) docResult.getNumberReturned();
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					listResult.add(OrderSearchEngine
							.documentToObjectByReflection(scoredDocument));
				}
			}

		} catch (Exception e) {
			System.out.println("Error when try to search order by user !");
			log.warning("Error when try to search order by user  !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void searchById(String orderId) {
		try {
			Query query = Query.newBuilder()
					.setOptions(QueryOptions.newBuilder().setLimit(1).build())
					.build("orderId:\"" + orderId + "\"");
			Results<ScoredDocument> docResult = INDEX.search(query);
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					currentItem = OrderSearchEngine
							.documentToObjectByReflection(scoredDocument);
				}
			}
			listResult = new ArrayList<OrderModel>();
			listResult.add(currentItem);
			totalMoney += currentItem.getTotalPrice();
			recentMoney += currentItem.getTotalPrice();
			totalReturn = 1;
			totalResult = 1;
		} catch (Exception e) {
			System.out.println("Error when try to search order : " + orderId);
			log.warning("Error when try to search order : " + orderId);
			log.warning(e.toString());
			e.printStackTrace();
			currentItem = null;
		}
	}

	public void searchByDealId(String dealId) {
		try {
			listResult = new ArrayList<OrderModel>();
			String queryString = "dealId:" + dealId;
			Query query = Query.newBuilder()
					.setOptions(QueryOptions.newBuilder().build())
					.build(queryString);
			// Query query = Query
			// .newBuilder()
			// .setOptions(
			// QueryOptions.newBuilder().setLimit(limit)
			// .setOffset(limit * (page - 1)).build())
			// .build(queryString.toString());

			Results<ScoredDocument> docResult = INDEX.search(query);
			totalResult = (int) docResult.getNumberFound();
			totalReturn = (int) docResult.getNumberReturned();
			if (docResult.getNumberFound() > 0) {
				for (ScoredDocument scoredDocument : docResult) {
					listResult.add(OrderSearchEngine
							.documentToObjectByReflection(scoredDocument));
				}
			}

		} catch (Exception e) {
			System.out.println("Error when try to search order by user !");
			log.warning("Error when try to search order by user  !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void searchAdvance(String salername, String shipCity,
			String shipDistrict, String username, int paymentType,
			String shipName, String shipAddress, String shipPhoneNumber,
			Date fromDate, Date toDate, int status, String checkOut) {
		try {
			StringBuilder queryString = new StringBuilder();
			Calendar cal = Calendar.getInstance();
			boolean check = false;
			if (salername != null && !salername.isEmpty()) {
				if (!check) {
					queryString.append("salername:" + salername);
					check = true;
				} else {
					queryString.append(" AND salername:" + salername);
				}
			}
			if (shipCity != null && !shipCity.isEmpty()) {
				if (!check) {
					queryString.append("shipCity:" + shipCity);
					check = true;
				} else {
					queryString.append(" AND shipCity:" + shipCity);
				}
			}
			if (shipDistrict != null && !shipDistrict.isEmpty()) {
				if (!check) {
					queryString.append("shipDistrict:" + shipDistrict);
					check = true;
				} else {
					queryString.append(" AND shipDistrict:" + shipDistrict);
				}

			}
			if (username != null && !username.isEmpty()) {
				if (!check) {
					queryString.append("username:" + username);
					check = true;
				} else {
					queryString.append(" AND username:" + username);
				}

			}
			if (paymentType != 0) {
				if (!check) {
					queryString.append("paymentType =" + paymentType);
					check = true;
				} else {
					queryString.append(" AND paymentType =" + paymentType);
				}
			}
			if (shipName != null && !shipName.isEmpty()) {
				if (!check) {
					queryString.append("shipName:" + shipName);
					check = true;
				} else {
					queryString.append(" AND shipName:" + shipName);
				}
			}
			if (shipAddress != null && !shipAddress.isEmpty()) {
				if (!check) {
					queryString.append("shipAddress:" + shipAddress);
					check = true;
				} else {
					queryString.append(" AND shipAddress:" + shipAddress);
				}
			}
			if (shipPhoneNumber != null && !shipPhoneNumber.isEmpty()) {
				if (!check) {
					queryString.append("shipPhoneNumber:" + shipPhoneNumber);
					check = true;
				} else {
					queryString.append(" AND shipPhoneNumber:"
							+ shipPhoneNumber);
				}
			}
			if (fromDate != null) {
				String fromDateString;
				cal.setTime(fromDate);
				fromDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) - 1);
				if (!check) {
					queryString.append("orderDate>" + fromDateString);
					check = true;
				} else {
					queryString.append(" AND orderDate>" + fromDateString);
				}
			}
			if (toDate != null) {
				String toDateString;
				cal.setTime(toDate);
				toDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) + 1);
				if (!check) {
					queryString.append("orderDate <" + toDateString);
					check = true;
				} else {
					queryString.append(" AND orderDate <" + toDateString);
				}
			}
			if (status != 0) {
				if (status == 11) {
					if (!check) {
						queryString.append("status =" + 4);
						check = true;
					} else {
						queryString.append(" AND status =" + 4);
					}
				} else if (status == 4) {
					if (!check) {
						queryString.append("status = " + 4 + " AND checkOut = "
								+ true);
						check = true;
					} else {
						queryString.append(" AND status =" + 4
								+ " AND checkOut = " + true);
					}
				} else {
					if (!check) {
						queryString.append("status =" + status);
						check = true;
					} else {
						queryString.append(" AND status =" + status);
					}
				}

			}
			if (checkOut != null && checkOut.length() > 0) {
				if (!check) {
					if (checkOut.equalsIgnoreCase("1")) {
						queryString.append("checkOut = false");
						check = true;
					} else if (checkOut.equalsIgnoreCase("2")) {
						queryString.append("checkOut = true");
						check = true;
					}
				} else {
					if (checkOut.equalsIgnoreCase("1")) {
						queryString.append(" AND checkOut = false");
					} else if (checkOut.equalsIgnoreCase("2")) {
						queryString.append(" AND checkOut = true");
					}
				}
			}

			listResult = new ArrayList<OrderModel>();
			Query query = Query.newBuilder().build(queryString.toString());
			Results<ScoredDocument> docResult = INDEX.search(query);
			totalResult = (int) docResult.getNumberFound();
			if (docResult.getNumberFound() > 0) {
				OrderModel obj = new OrderModel();
				for (ScoredDocument scoredDocument : docResult) {
					obj = OrderSearchEngine
							.documentToObjectByReflection(scoredDocument);
					totalMoney += obj.getTotalPrice();
				}
			}

			query = Query
					.newBuilder()
					.setOptions(
							QueryOptions.newBuilder().setLimit(limit)
									.setOffset(limit * (page - 1)).build())
					.build(queryString.toString());
			docResult = INDEX.search(query);
			totalReturn = (int) docResult.getNumberReturned();
			if (docResult.getNumberFound() > 0) {
				OrderModel obj = new OrderModel();
				for (ScoredDocument scoredDocument : docResult) {
					obj = OrderSearchEngine
							.documentToObjectByReflection(scoredDocument);
					recentMoney += obj.getTotalPrice();
					listResult.add(obj);
				}
			}
		} catch (Exception e) {
			System.out.println("Error when try to search order !");
			log.warning("Error when try to search order !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

	public void searchAdvanceByCheckOutTime(String strCity, Date fromDate,
			Date toDate) {
		try {
			StringBuilder queryString = new StringBuilder();
			Calendar cal = Calendar.getInstance();
			boolean check = false;
			if (strCity != null && !strCity.isEmpty()) {
				if (!check) {
					queryString.append("shipCity:" + strCity);
					check = true;
				} else {
					queryString.append(" AND shipCity:" + strCity);
				}
			}
			if (fromDate != null) {
				String fromDateString;
				cal.setTime(fromDate);
				fromDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) - 1);
				if (!check) {
					queryString.append("checkOutTime>" + fromDateString);
					check = true;
				} else {
					queryString.append(" AND checkOutTime>" + fromDateString);
				}
			}
			if (toDate != null) {
				String toDateString;
				cal.setTime(toDate);
				toDateString = cal.get(Calendar.YEAR) + "-"
						+ (cal.get(Calendar.MONTH) + 1) + "-"
						+ (cal.get(Calendar.DATE) + 1);
				if (!check) {
					queryString.append("checkOutTime <" + toDateString);
					check = true;
				} else {
					queryString.append(" AND checkOutTime <" + toDateString);
				}
			}

			listResult = new ArrayList<OrderModel>();
			Query query = Query.newBuilder().build(queryString.toString());
			Results<ScoredDocument> docResult = INDEX.search(query);
			totalResult = (int) docResult.getNumberFound();
			if (docResult.getNumberFound() > 0) {
				OrderModel obj = new OrderModel();
				for (ScoredDocument scoredDocument : docResult) {
					obj = OrderSearchEngine
							.documentToObjectByReflection(scoredDocument);
					totalMoney += obj.getTotalPrice();
				}
			}

			query = Query
					.newBuilder()
					.setOptions(
							QueryOptions.newBuilder().setLimit(limit)
									.setOffset(limit * (page - 1)).build())
					.build(queryString.toString());
			docResult = INDEX.search(query);
			totalReturn = (int) docResult.getNumberReturned();
			if (docResult.getNumberFound() > 0) {
				OrderModel obj = new OrderModel();
				for (ScoredDocument scoredDocument : docResult) {
					obj = OrderSearchEngine
							.documentToObjectByReflection(scoredDocument);
					recentMoney += obj.getTotalPrice();
					listResult.add(obj);
				}
			}
		} catch (Exception e) {
			System.out.println("Error when try to search order !");
			log.warning("Error when try to search order !");
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<OrderModel>();
		}
	}

}
